home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-09-09 | 31.4 KB | 1,025 lines | [TEXT/CWIE] |
- // a different implimentation of NCMDrawMatchedPicture
- //
- // David Hayward
- // Developer Technical Support
- // AppleLink: DEVSUPPORT
- //
- // Copyright 1995-1998, Apple Computer,Inc
- //
- // 12/13/94 david first cut
- // 12/13/94 david fixed which caused 16-bit picts to crash because pict was not
- // locked in memory
- // 9/25/97 ebb mods to keep track of ticks and pixel counts
- //
- // The ColorSync 1.0 DrawMatchedPicture, does not use bottlenecks as one might expect.
- // It installs a bottleneck routine for PicComments (so that it can watch the
- // embedded profiles go by) but does not do the actual matching in bottleneck routines.
- // Instead, It installs a ColorSearchProc in the current GDevice. Inside the
- // ColorSearchProc, each color is matched - one at a time. This implementation has
- // some advantages but one big problem is that it is painfully slow on PixMaps because,
- // even if the PixMap only contains 16 colors, each pixel is matched.
- //
- // This has been changed in CS 2.0. In order to boost performance of PixMaps (which are,
- // after all, quite common) are now matched in the bottleneck instead of the ColorSearchProc.
- //
- // Interesting side note:
- // If you record DrawMatchedPicture (in the case of CS1) or NCMDrawMatchedPicture (in the
- // case of CS2) into another picture using the following code:
- // *newPict = OpenPicture( &pictRect ) ; // start recording
- // NCMDrawMatchedPicture( pict, destProf, &pictRect ) ;
- // ClosePicture() ; // stop recording
- // then the resulting newPict will contain the same data as the original pict. It does
- // not contain the matched picture information as you might suspect.
- //
- //
- // This file contains a different implimentation of NCMDrawMatchedPicture.
- // it differs from NCMDrawMatchedPicture in that it uses bottleneck
- // procs to do all the matching instead of installing ColorSearchProc
- // This meens that if you record myDrawMatchedPicture in another picture,
- // then the resulting picture will contain the mached color and may be considerably
- // smaller because it does not contain any profiles. myDrawMatchedPicture
- // allows an application to pre-match a picture once, and then use the resulting pict
- // for fast updates. Of course, if the source or dest profiles are changed then the pict
- // will need to be re-matched.
- //
- // This file also contains two other routines which share a lot of code of myDrawMatchedPicture
- // myDrawProofoedPicture - matches a pict according to 3 profiles (source to destination
- // to preview) so that you can do a print-preview of the color output
- // myDrawCheckedPicture - gamut checks a pict according to the source and printer profiles
- // the resulting pict is black for all points out of gamut and white everywhere else
- //
- // This certainly not fully polished yet, being as that I have only tested
- // it out on only a handful of pict files and profiles.
-
-
- #include <QuickDraw.h>
- #include <QDOffscreen.h>
- #include <CMApplication.h>
-
- #include "qdUtils.h"
- #include "colorsyncUtils.h"
- #include "myDrawMatchedPict.h"
-
- /**\
- |**| ==============================================================================
- |**| PRIVATE DEFINES
- |**| ==============================================================================
- \**/
- #define kMatch 1
- #define kProof 2
- #define kCheck 3
-
- #define kForeColor 1
- #define kBackColor 2
-
- #define kPenPixPat 1
- #define kFillPixPat 2
- #define kBackPixPat 3
-
-
- /**\
- |**| ==============================================================================
- |**| PRIVATE GLOBALS
- |**| ==============================================================================
- \**/
- static OSErr gError = noErr ;
- static unsigned long gTicks = 0;
- static unsigned long gPixels = 0;
- static CMWorldRef gCW = nil;
- static CMProfileRef gSrceProf = nil;
- static CMProfileRef gDestProf = nil;
- static CMProfileRef gPrevProf = nil;
- static short gDrawMode = 0;
- static Boolean gMatchingEnabled = true ;
- static unsigned long gCount = 0;
- static PicHandle gPict = nil ;
-
- static RGBColor gWhiteRGB = { 0xFFFF,0xFFFF,0xFFFF } ;
- static RGBColor gBlackRGB = { 0x0000,0x0000,0x0000 } ;
-
- // Match Buffers
- static RGBColor gLastForeColor ;
- static RGBColor gLastForeColorMatched ;
- static Boolean gLastForeColorNeedsUpdate ;
- static RGBColor gLastBackColor ;
- static RGBColor gLastBackColorMatched ;
- static Boolean gLastBackColorNeedsUpdate ;
- static PixPatHandle gLastPenPixPat ;
- static PixPatHandle gLastFillPixPat ;
- static PixPatHandle gLastBackPixPat ;
-
- // Profile Buffers
- static CMProfileRef** gProfileListHdl ;
- static long gProfileListCount ;
-
- /**\
- |**| ==============================================================================
- |**| PRIVATE FUNCTION PROTOTYPES
- |**| ==============================================================================
- \**/
- void SetError ( OSErr err ) ;
- Boolean SameColor ( RGBColor *rgbA, RGBColor *rgbB ) ;
- CMError ChangeRGBColor ( RGBColor *rgb ) ;
- void ChangePortColor ( short which ) ;
- void UnChangePortColor ( short which ) ;
-
- CMError ChangePixPat ( PixPatHandle pat ) ;
- void ChangePortPixPat ( short which ) ;
- void UnChangePortPixPat ( short which ) ;
-
- void ChangePortPixPatForVerb ( GrafVerb verb ) ;
- void UnChangePortPixPatForVerb( GrafVerb verb ) ;
-
- pascal void TextProc ( short byteCount, Ptr textAddr, Point numer, Point denom ) ;
- pascal void LineProc ( Point endPoint ) ;
- pascal void RectProc ( GrafVerb verb, Rect *r ) ;
- pascal void RRectProc ( GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight ) ;
- pascal void OvalProc ( GrafVerb verb, Rect *r ) ;
- pascal void ArcProc ( GrafVerb verb, Rect *r, short startAngle, short arcAngle ) ;
- pascal void PolyProc ( GrafVerb verb, PolyHandle poly ) ;
- pascal void RgnProc ( GrafVerb verb, RgnHandle rgn ) ;
- pascal void BitsProc ( BitMap *bitPtr, Rect *srcRect, Rect *dstRect, short mode, RgnHandle maskRgn ) ;
- pascal void CommentProc ( short kind, short dataSize, Handle dataHandle ) ;
-
- void DisposeColorWorld ( void ) ;
- void BuildColorWorld ( CMProfileRef srceProf ) ;
-
- OSErr AllocateProfileBuffers ( void ) ;
- OSErr AppendProfileBuffers ( CMProfileRef prof ) ;
- void DisposeProfileBuffers ( void ) ;
-
- OSErr AllocateMatchBuffers ( void ) ;
- void DisposeMatchBuffers ( void ) ;
-
- OSErr myDrawPicture ( PicHandle pict,
- CMProfileRef srceProf,
- CMProfileRef destProf,
- CMProfileRef prevProf,
- Rect *rect,
- unsigned long *ticks,
- unsigned long *pixels ) ;
-
- short CalculateRowBytesFromRect ( Rect *theRect, short pixelSize) ;
-
-
-
- /*------------------------------------------------------------------------------*\
- SetError
- *------------------------------------------------------------------------------*
- This routine sets the current error state globalif it hasn't be set already.
- \*------------------------------------------------------------------------------*/
- static void SetError ( OSErr err )
- {
- if ( (gError==noErr) && (err!=noErr) )
- gError = err ;
- }
-
-
- /*------------------------------------------------------------------------------*\
- SetError
- *------------------------------------------------------------------------------*
- This routine returns true if two colors have tha same RGB values.
- \*------------------------------------------------------------------------------*/
- static Boolean SameColor ( RGBColor *rgbA, RGBColor *rgbB )
- {
- return ( (rgbA->red == rgbB->red) &&
- (rgbA->green == rgbB->green) &&
- (rgbA->blue == rgbB->blue) ) ;
- }
-
-
- /*------------------------------------------------------------------------------*\
- ChangeRGBColor
- *------------------------------------------------------------------------------*
- This routine changes an RGBColor according to the current state if the
- gDrawMode, gMatchingEnabled, and gCW globals. If the gDrawMode is kCheck
- the the color is gamut checked according to the gCW color world. If the
- gDrawMode is kMatch or kProof, then the color is matched according to
- the gCW color world.
- \*------------------------------------------------------------------------------*/
- static CMError ChangeRGBColor ( RGBColor *rgb )
- {
- CMColor cmcolor ;
- CMError cmerr=noErr ;
- long result=0 ;
-
- if (gDrawMode != kCheck) // if these two conditions are true
- if (gMatchingEnabled == false) return noErr;// then no work needs to be done
-
- cmcolor.rgb.red = rgb->red ;
- cmcolor.rgb.green = rgb->green ;
- cmcolor.rgb.blue = rgb->blue ;
-
- if (gDrawMode == kCheck)
- {
- if (gMatchingEnabled)
- {
- cmerr = CWCheckColors( gCW, &cmcolor, 1, &result) ;
- if (result)
- cmcolor.rgb.red = cmcolor.rgb.green = cmcolor.rgb.blue = 0x0000 ;// black
- else
- cmcolor.rgb.red = cmcolor.rgb.green = cmcolor.rgb.blue = 0xFFFF ;// white
- }
- else
- cmcolor.rgb.red = cmcolor.rgb.green = cmcolor.rgb.blue = 0xFFFF ;// white
- }
- else
- if (gMatchingEnabled)
- cmerr = CWMatchColors( gCW, &cmcolor, 1 ) ;
-
- if ( cmerr ) return cmerr ;
-
- rgb->red = cmcolor.rgb.red ;
- rgb->green = cmcolor.rgb.green ;
- rgb->blue = cmcolor.rgb.blue ;
-
- return cmerr;
- }
-
-
- /*------------------------------------------------------------------------------*\
- ChangePortColor
- *------------------------------------------------------------------------------*
- This routine changes one of the RGBColors in the current CGrafPort by
- calling ChangeRGBColor(). For example, if which==kForeColor then the port's
- rgbFgColor is changed. The color before and after the change is buffered
- in globals so that, if the the the next object to be drawn uses the same
- color, then the change can be done quickly.
- \*------------------------------------------------------------------------------*/
- static void ChangePortColor ( short which )
- {
- RGBColor *curentColor ;
- RGBColor *lastColor ;
- RGBColor *lastColorMatched ;
- Boolean *lastColorNeedsUpdate ;
- CMError cmerr=noErr ;
-
- if (gDrawMode != kCheck) // if these two conditions are true
- if (gMatchingEnabled == false) return ; // then no work needs to be done
-
- switch (which)
- {
- case kForeColor :
- curentColor = &(((CGrafPtr)qd.thePort)->rgbFgColor) ;
- lastColor = &gLastForeColor ;
- lastColorMatched = &gLastForeColorMatched ;
- lastColorNeedsUpdate = &gLastForeColorNeedsUpdate ;
- break ;
- case kBackColor :
- curentColor = &(((CGrafPtr)qd.thePort)->rgbBkColor) ;
- lastColor = &gLastBackColor ;
- lastColorMatched = &gLastBackColorMatched ;
- lastColorNeedsUpdate = &gLastBackColorNeedsUpdate ;
- break ;
- default :
- return ;
- break ;
- }
-
- if ( SameColor( lastColor, curentColor ) )
- {
- if ( *lastColorNeedsUpdate )
- cmerr = ChangeRGBColor( curentColor ) ;
- else
- *curentColor = *lastColorMatched ; // current = lastMatched
- }
- else
- {
- *lastColor = *curentColor ; // last = curent
- cmerr = ChangeRGBColor( curentColor ) ; // match curent
- }
-
- if (!cmerr)
- {
- *lastColorMatched = *curentColor ; // lastMatched = curent
- *lastColorNeedsUpdate = false ;
- }
- SetError( cmerr ) ;
- }
- /*------------------------------------------------------------------------------*\
- UnChangePortColor
- *------------------------------------------------------------------------------*
- This routine un-changes one of the RGBColors in the current CGrafPort by
- by restoring the appropriate buffered global.
- \*------------------------------------------------------------------------------*/
- static void UnChangePortColor ( short which )
- {
- if (gDrawMode != kCheck) // if these two conditions are true
- if (gMatchingEnabled == false) return ; // then no work needs to be done
-
- switch (which)
- {
- case kForeColor :
- (((CGrafPtr)qd.thePort)->rgbFgColor) = gLastForeColor ;
- break ;
- case kBackColor :
- (((CGrafPtr)qd.thePort)->rgbBkColor) = gLastBackColor ;
- break ;
- default :
- break ;
- }
- }
-
-
-
- ////////////////////////////////////////////////////////////////////////////////
-
-
- /*------------------------------------------------------------------------------*\
- ChangePixPat
- *------------------------------------------------------------------------------*
- This routine changes an PixPat according to the current state if the
- gDrawMode, gMatchingEnabled, and gCW globals. If the gDrawMode is kCheck
- the the PixPat is gamut checked according to the gCW color world. If the
- gDrawMode is kMatch or kProof, then the PixPat is matched according to
- the gCW color world.
- ** NOTE **
- this routine still needs work so that it can properly hanlde type-1 and
- type-2 PixMaps. The commented psuedo-code is a rought outline of what
- needs to be added.
- \*------------------------------------------------------------------------------*/
- static CMError ChangePixPat ( PixPatHandle pat )
- {
- CMError cmerr=noErr;
-
- if (gDrawMode != kCheck) // if these two conditions are true
- if (gMatchingEnabled == false) return noErr; // then no work needs to be done
-
- switch ((**pat).patType)
- {
- case 0: /* one-bit patterns are drawn in the foreground and background color. */
- ChangePortColor( kForeColor ) ;
- ChangePortColor( kBackColor ) ;
- break;
- case 1: /* Type 1 PixPats have a color table. */
- if (gDrawMode == kCheck)
- {
- if (gMatchingEnabled)
- {
- // if pat is indexed
- // CWCheckPixMap()
- // copy bitbap from above into a new pattern
- // else
- // if pat doesn't have a full color table
- // fill in the extra entries with colors between fg and bk
- // for each color in table
- // ChangeRGBColor()
- }
- else
- {
- // make pat white ;// white
- }
- }
- else
- {
- if (gMatchingEnabled)
- {
- // if pat is indexed and doesn't has a full color table
- // fill in the extra entries with colors between fg and bk
- cmerr = CWMatchPixMap( gCW, (*(**pat).patMap), nil, nil ) ;
- }
- }
- PixPatChanged( pat ) ;
- break;
- case 2: /* Type 2 PixPats have 5 color entries where the 5th is the desired color */
- // ChangeRGBColor() to chane the 5th colortable entry
- PixPatChanged( pat ) ;
- break;
- }
- return cmerr ;
- }
-
-
- /*------------------------------------------------------------------------------*\
- ChangePortPixPat
- *------------------------------------------------------------------------------*
- This routine changes one of the PixPats in the current CGrafPort by
- calling ChangePixPat(). For example, if which==kPenPixPat then the port's
- pnPixPat is changed. The PixPat before the change is buffered in a
- global so that it is posible to restore the orginal PixPat quickly.
- \*------------------------------------------------------------------------------*/
- static void ChangePortPixPat ( short which )
- {
- PixPatHandle *curentPixPat ;
- PixPatHandle *lastPixPat ;
- CMError cmerr=noErr ;
-
- if (gDrawMode != kCheck) // if these two conditions are true
- if (gMatchingEnabled == false) return ; // then no work needs to be done
-
- switch (which)
- {
- case kPenPixPat :
- curentPixPat = &(((CGrafPtr)qd.thePort)->pnPixPat) ;
- lastPixPat = &gLastPenPixPat ;
- break ;
- case kFillPixPat :
- curentPixPat = &(((CGrafPtr)qd.thePort)->fillPixPat) ;
- lastPixPat = &gLastFillPixPat ;
- break ;
- case kBackPixPat :
- curentPixPat = &(((CGrafPtr)qd.thePort)->bkPixPat) ;
- lastPixPat = &gLastBackPixPat ;
- break ;
- default :
- return ;
- break ;
- }
-
- CopyPixPat( *curentPixPat, *lastPixPat) ; // last = curent
- cmerr = ChangePixPat( *curentPixPat ) ; // match curent
- SetError( cmerr ) ;
- }
- /*------------------------------------------------------------------------------*\
- UnChangePortPixPat
- *------------------------------------------------------------------------------*
- This routine un-changes one of the PixPats in the current CGrafPort by
- by restoring the appropriate buffered global.
- \*------------------------------------------------------------------------------*/
- static void UnChangePortPixPat ( short which )
- {
- PixPatHandle *curentPixPat ;
- PixPatHandle *lastPixPat ;
-
- if (gDrawMode != kCheck) // if these two conditions are true
- if (gMatchingEnabled == false) return ; // then no work needs to be done
-
- switch (which)
- {
- case kPenPixPat :
- curentPixPat = &(((CGrafPtr)qd.thePort)->pnPixPat) ;
- lastPixPat = &gLastPenPixPat ;
- break ;
- case kFillPixPat :
- curentPixPat = &(((CGrafPtr)qd.thePort)->fillPixPat) ;
- lastPixPat = &gLastFillPixPat ;
- break ;
- case kBackPixPat :
- curentPixPat = &(((CGrafPtr)qd.thePort)->bkPixPat) ;
- lastPixPat = &gLastBackPixPat ;
- break ;
- default :
- return ;
- break ;
- }
-
- if ( (***lastPixPat).patType == 0 )
- {
- UnChangePortColor( kForeColor ) ;
- UnChangePortColor( kBackColor ) ;
- }
-
- CopyPixPat( *lastPixPat, *curentPixPat ) ; // curent = last
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
-
-
- /*------------------------------------------------------------------------------*\
- ChangePortPixPatForVerb
- *------------------------------------------------------------------------------*
- This routine changes one of the PixPats in the current CGrafPort by
- calling ChangePortPixPat(). For example, if the GrafVerb verb==erase
- then the port's kBackPixPat is changed.
- \*------------------------------------------------------------------------------*/
- static void ChangePortPixPatForVerb ( GrafVerb verb )
- {
- if (gDrawMode != kCheck) // if these two conditions are true
- if (gMatchingEnabled == false) return ; // then no work needs to be done
- switch (verb)
- {
- case kQDGrafVerbFrame:
- case kQDGrafVerbPaint: /* Framed and painted objects are drawn in the pen PixPat. */
- ChangePortPixPat( kPenPixPat ) ;
- break;
- case kQDGrafVerbErase: /* Erased objects are drawn in the background PixPat. */
- ChangePortPixPat( kBackPixPat ) ;
- break;
- case kQDGrafVerbFill: /* Filled objects are drawn in the fill PixPat. */
- ChangePortPixPat( kFillPixPat ) ;
- break;
- }
- }
- /*------------------------------------------------------------------------------*\
- UnChangePortPixPatForVerb
- *------------------------------------------------------------------------------*
- This routine un-changes one of the PixPats in the current CGrafPort by
- by calling UnChangePortPixPat().
- \*------------------------------------------------------------------------------*/
- static void UnChangePortPixPatForVerb ( GrafVerb verb )
- {
- if (gDrawMode != kCheck) // if these two conditions are true
- if (gMatchingEnabled == false) return ; // then no work needs to be done
- switch (verb)
- {
- case kQDGrafVerbFrame:
- case kQDGrafVerbPaint: /* Framed and painted objects are drawn in the pen PixPat. */
- UnChangePortPixPat( kPenPixPat ) ;
- break;
- case kQDGrafVerbErase: /* Erased objects are drawn in the background PixPat. */
- UnChangePortPixPat( kBackPixPat ) ;
- break;
- case kQDGrafVerbFill: /* Filled objects are drawn in the fill PixPat. */
- UnChangePortPixPat( kFillPixPat ) ;
- break;
- }
- }
-
-
-
- /**\
- |**| ==============================================================================
- |**| BOTTLENECK ROUTINES
- |**| ==============================================================================
- \**/
-
-
- static pascal void TextProc ( short byteCount, Ptr textAddr, Point numer, Point denom )
- { /* Text is drawn with the foreground and background colors.*/
- ChangePortColor( kForeColor ) ;
- ChangePortColor( kBackColor ) ;
- StdText( byteCount, textAddr, numer, denom ) ;
- UnChangePortColor( kForeColor ) ;
- UnChangePortColor( kBackColor ) ;
- }
-
-
- static pascal void LineProc ( Point endPoint )
- { /* Lines are drawn with the pen PixPat. */
- ChangePortPixPat( kPenPixPat ) ;
- StdLine( endPoint ) ;
- UnChangePortPixPat( kPenPixPat ) ;
- }
-
-
- static pascal void RectProc ( GrafVerb verb, Rect *r )
- { // Rects are drawn according to the GrafVerb
- ChangePortPixPatForVerb( verb ) ;
- StdRect( verb, r ) ;
- UnChangePortPixPatForVerb( verb ) ;
- }
-
-
- static pascal void RRectProc ( GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight )
- { // RRects are drawn according to the GrafVerb
- ChangePortPixPatForVerb( verb ) ;
- StdRRect( verb, r, ovalWidth, ovalHeight ) ;
- UnChangePortPixPatForVerb( verb ) ;
- }
-
-
- static pascal void OvalProc ( GrafVerb verb, Rect *r )
- { // Ovals are drawn according to the GrafVerb
- ChangePortPixPatForVerb( verb ) ;
- StdOval( verb, r ) ;
- UnChangePortPixPatForVerb( verb ) ;
- }
-
-
- static pascal void ArcProc ( GrafVerb verb, Rect *r, short startAngle, short arcAngle )
- { // Arcs are drawn according to the GrafVerb
- ChangePortPixPatForVerb( verb ) ;
- StdArc( verb, r, startAngle, arcAngle ) ;
- UnChangePortPixPatForVerb( verb ) ;
- }
-
-
- static pascal void PolyProc ( GrafVerb verb, PolyHandle poly )
- { // Polys are drawn according to the GrafVerb
- ChangePortPixPatForVerb( verb ) ;
- StdPoly( verb, poly ) ;
- UnChangePortPixPatForVerb( verb ) ;
- }
-
-
- static pascal void RgnProc ( GrafVerb verb, RgnHandle rgn )
- { // Regions are drawn according to the GrafVerb
- ChangePortPixPatForVerb( verb ) ;
- StdRgn( verb, rgn ) ;
- UnChangePortPixPatForVerb( verb ) ;
- }
-
-
- static pascal void BitsProc ( BitMap *bitPtr, Rect *srcRect, Rect *dstRect, short mode, RgnHandle maskRgn )
- {
- CMError cmerr ;
- PixMapPtr pixMapPtr;
- short rowBytes;
- unsigned long ticks;
-
- /* Get the PixMap that we are about to draw.
- SrcBits might be a BitMap, or one of
- two different kinds of PixMap pointers. */
-
- rowBytes = (*bitPtr).rowBytes; /* local copy of rowBytes */
-
- // Update the number of pixels we're processing
- gPixels += (srcRect->right - srcRect->left) *
- (srcRect->bottom - srcRect->top);
-
- if (rowBytes & 0x8000) /* if high bit set then its a pixmap */
- {
- if (rowBytes & 0x4000) /* next to high bit set? */
- {
- HLock( (Handle) (*((PixMapHandle*)bitPtr)) ) ;
- pixMapPtr = (**((PixMapHandle*)bitPtr)) ; /* bitPtr is a ptr to a PixMap handle */
- }
- else
- pixMapPtr = (PixMapPtr) bitPtr; /* bitPtr is a ptr to a PixMap */
-
-
- if (gDrawMode == kCheck)
- {
- BitMap bm;
-
- // create bitmap
- bm.bounds = (*bitPtr).bounds ;
- bm.rowBytes = CalculateRowBytesFromRect( &(bm.bounds), 1 ) ;
- bm.baseAddr = NewPtrClear( bm.rowBytes*(bm.bounds.bottom-bm.bounds.top) );
-
- if (gMatchingEnabled)
- {
- ticks = TickCount();
- cmerr = CWCheckPixMap( gCW, pixMapPtr, nil, nil, (BitMap *)&bm) ;
- gTicks += TickCount() - ticks;
- SetError( cmerr ) ;
- }
- // else leave offscreen as all-white
-
- StdBits( (BitMap *)&bm, srcRect, dstRect, mode, maskRgn) ;
-
- // dispose bitmap
- DisposePtr( (Ptr)bm.baseAddr );
- }
- else
- {
- if (gMatchingEnabled)
- {
- ticks = TickCount();
- cmerr = CWMatchPixMap( gCW, pixMapPtr, nil, nil ) ;
- gTicks += TickCount() - ticks;
- SetError( cmerr ) ;
- }
- StdBits( bitPtr, srcRect, dstRect, mode, maskRgn) ;
- }
-
- if (rowBytes & 0x4000) /* next to high bit set? */
- HUnlock( (Handle) (*((PixMapHandle*)bitPtr)) ) ;
- }
- else
- { /* It's just a BitMap; it will use the background and foreground colors. */
- ChangePortColor( kForeColor ) ;
- ChangePortColor( kBackColor ) ;
- StdBits( bitPtr, srcRect, dstRect, mode, maskRgn) ;
- UnChangePortColor( kForeColor ) ;
- UnChangePortColor( kBackColor ) ;
- }
- }
-
- /* Routine - CalculateRowbytesFromRect */
- /* Given a pointer to a rectangle and number of bits per pixel, this routine calculates
- the row bytes of an image */
-
-
- short CalculateRowBytesFromRect(Rect *theRect, short pixelSize)
- {
- short rowBytes ;
- short imageWidth ;
-
- imageWidth = theRect->right - theRect->left ;
- rowBytes = (pixelSize * ((imageWidth + 15)/16)) * 2 ;
- return rowBytes ;
- }
-
-
- static pascal void CommentProc ( short kind, short dataSize, Handle dataHandle )
- {
- long selector ;
- CMProfileRef srceProf ;
- CMError cmerr ;
-
- switch (kind)
- {
- case cmBeginProfile :
- gCount ++ ; // we found a version 1 profile
- if ( gMatchingEnabled == false ) break ;
- cmerr = GetIndexedProfileFromPicHandle( gPict, gCount, &srceProf, nil ) ;
- SetError( cmerr ) ;
- BuildColorWorld( srceProf ) ;
- cmerr = CMCloseProfile( srceProf ) ;
- break ;
-
- case cmEndProfile :
- if ( gMatchingEnabled == false ) break ;
- BuildColorWorld( gSrceProf ) ;
- break ;
-
- case cmEnableMatching :
- gMatchingEnabled = true ;
- break ;
-
- case cmDisableMatching :
- if ( gMatchingEnabled == false ) break ;
- gMatchingEnabled = false ;
- break ;
-
- case cmComment:
- if ( dataSize <= 4 ) break; // dataSize too small for selector so break
- selector = *((long *)(*dataHandle)) ; // get the selector from 1st long in data
- switch (selector)
- {
- case cmBeginProfileSel :
- gCount ++ ; // we found a version 2 profile
- if ( gMatchingEnabled == false ) break ;
- cmerr = GetIndexedProfileFromPicHandle( gPict, gCount, &srceProf, nil ) ;
- SetError( cmerr ) ;
- BuildColorWorld( srceProf ) ;
- cmerr = AppendProfileBuffers( srceProf ) ;
- cmerr = CMCloseProfile( srceProf ) ;
- break ;
-
- case cmProfileIdentifierSel :
- gCount ++ ; // we found a version 2 profile id
- if ( gMatchingEnabled == false ) break ;
- cmerr = GetIndexedProfileFromPicHandle( gPict, gCount, &srceProf, nil ) ;
- SetError( cmerr ) ;
- BuildColorWorld( srceProf ) ;
- cmerr = CMCloseProfile( srceProf ) ;
- break ;
-
- case cmContinueProfileSel :
- case cmEndProfileSel :
- break ;
- }
- break ;
-
- default:
- StdComment( kind, dataSize, dataHandle ) ;
- break ;
- }
- }
-
-
-
- static void DisposeColorWorld ( void )
- {
- if ( gCW ) CWDisposeColorWorld( gCW ) ;
- gCW = nil ;
- }
-
-
- static void BuildColorWorld ( CMProfileRef srceProf )
- {
- CMError cmerr ;
- CMConcatProfileSet *profileSetPtr ;
- CMProfileRef foundProf=nil;
-
- DisposeColorWorld() ;
-
- // should check to see if the profs are kosher
-
- if ( IsPseudoProfile(srceProf) )
- { // search buffered profiles
- HLock( (Handle)gProfileListHdl );
- cmerr = PseudoProfileListSearch( srceProf, &foundProf,
- *gProfileListHdl, gProfileListCount ) ;
- if (cmerr || !foundProf) // if none found
- { // search profiles folder
- cmerr = PseudoProfileFolderSearch( srceProf, &foundProf) ;
- if (cmerr || !foundProf) // if none found
- cmerr = CMGetSystemProfile(&foundProf) ;
- }
- if (!cmerr) srceProf = foundProf ;
- }
-
- if ( gDrawMode==kMatch || gDrawMode==kCheck )
- {
- cmerr = NCWNewColorWorld( &gCW, srceProf, gDestProf ) ;
- }
- else // ( gDrawMode==kProof)
- {
- profileSetPtr = (CMConcatProfileSet *)NewPtr( sizeof(CMConcatProfileSet) +
- 2*sizeof(CMProfileRef) ) ;
- // use the cmm of the dest profile
- profileSetPtr->keyIndex = 1 ;
- profileSetPtr->count = 3 ;
- profileSetPtr->profileSet[0] = srceProf ;
- profileSetPtr->profileSet[1] = gDestProf ;
- profileSetPtr->profileSet[2] = gPrevProf ;
- cmerr = CWConcatColorWorld( &gCW, profileSetPtr) ;
- DisposePtr( (Ptr)profileSetPtr ) ;
- }
-
- if (foundProf)
- CMCloseProfile(foundProf) ;
-
- SetError( cmerr ) ;
-
- gLastForeColorNeedsUpdate = true ;
- gLastBackColorNeedsUpdate = true ;
- }
-
-
- static OSErr AllocateProfileBuffers ( void )
- {
- gProfileListHdl = (CMProfileRef**)NewHandle( 0 ) ;
- if (gProfileListHdl==nil)
- return MemError();
-
- gProfileListCount = 0 ;
- return noErr ;
- }
- static OSErr AppendProfileBuffers ( CMProfileRef prof )
- {
- OSErr err;
- Size oldsize;
- CMProfileRef newProf;
-
- oldsize = GetHandleSize((Handle)gProfileListHdl);
- if (oldsize<0)
- return oldsize;
-
- SetHandleSize( (Handle)gProfileListHdl,
- oldsize + sizeof(CMProfileRef) );
- err = MemError();
- if (err) return err;
-
- err = ReOpenProfileRef( &newProf, prof ) ;
- if (err) return err;
-
- (*gProfileListHdl)[gProfileListCount] = newProf ;
- gProfileListCount++;
- return noErr ;
- }
- static void DisposeProfileBuffers ( void )
- {
- long i;
- for ( i=0; i<gProfileListCount; i++ )
- CMCloseProfile( (*gProfileListHdl)[i]) ;
- DisposeHandle( (Handle)gProfileListHdl ) ;
- gProfileListCount = 0 ;
- }
-
-
- static OSErr AllocateMatchBuffers ( void )
- {
- gLastForeColor = gBlackRGB ;
- gLastForeColorMatched = gBlackRGB ;
- gLastBackColor = gWhiteRGB ;
- gLastBackColorMatched = gWhiteRGB ;
-
- gLastPenPixPat = NewPixPat() ;
- gLastFillPixPat = NewPixPat() ;
- gLastBackPixPat = NewPixPat() ;
-
- gLastForeColorNeedsUpdate =
- gLastBackColorNeedsUpdate = true ;
- return noErr ;
- }
- static void DisposeMatchBuffers ( void )
- {
- DisposePixPat( gLastPenPixPat ) ;
- DisposePixPat( gLastFillPixPat ) ;
- DisposePixPat( gLastBackPixPat ) ;
- }
-
-
- static OSErr myDrawPicture ( PicHandle pict,
- CMProfileRef srceProf,
- CMProfileRef destProf,
- CMProfileRef prevProf,
- Rect *rect,
- unsigned long *ticks,
- unsigned long *pixels )
- {
- OSErr err = noErr ;
- CQDProcs procs ;
- CQDProcsPtr oldProcs ;
-
- SetStdCProcs(&procs) ;
-
- procs.textProc = NewQDTextProc ( TextProc ) ;
- procs.lineProc = NewQDLineProc ( LineProc ) ;
- procs.rectProc = NewQDRectProc ( RectProc ) ;
- procs.rRectProc = NewQDRRectProc ( RRectProc ) ;
- procs.ovalProc = NewQDOvalProc ( OvalProc ) ;
- procs.arcProc = NewQDArcProc ( ArcProc ) ;
- procs.polyProc = NewQDPolyProc ( PolyProc ) ;
- procs.rgnProc = NewQDRgnProc ( RgnProc ) ;
- procs.bitsProc = NewQDBitsProc ( BitsProc ) ;
- procs.commentProc = NewQDCommentProc( CommentProc ) ;
-
- oldProcs = (*(CGrafPtr)qd.thePort).grafProcs ; // must be a color port
- (*(CGrafPtr)qd.thePort).grafProcs = &procs ; // must be a color port
-
- if (!err) err = AllocateMatchBuffers() ;
- if (!err) err = AllocateProfileBuffers() ;
- if (!err)
- {
- gMatchingEnabled = true ;
- gError = noErr ;
- gPict = pict ;
- gCount = 0 ;
- gTicks = 0 ;
- gPixels = 0;
- gSrceProf = srceProf ;
- gDestProf = destProf ;
- gPrevProf = prevProf ;
- if ( srceProf==nil ) CMGetSystemProfile( &gSrceProf ) ;
- if ( destProf==nil ) CMGetSystemProfile( &gDestProf ) ;
- if ( prevProf==nil ) CMGetSystemProfile( &gPrevProf ) ;
- BuildColorWorld( gSrceProf ) ;
-
- HLock( (Handle) pict ) ;
- DrawPicture( pict, rect ) ;
- HUnlock( (Handle) pict ) ;
-
- err = gError ;
- DisposeColorWorld() ;
- if ( srceProf==nil ) CMCloseProfile( gSrceProf ) ;
- if ( destProf==nil ) CMCloseProfile( gDestProf ) ;
- if ( prevProf==nil ) CMCloseProfile( gPrevProf ) ;
-
- DisposeMatchBuffers() ;
- DisposeProfileBuffers() ;
- }
-
- (*(CGrafPtr)qd.thePort).grafProcs = oldProcs ; // must be a color port
-
- DisposeRoutineDescriptor( procs.textProc ) ;
- DisposeRoutineDescriptor( procs.lineProc ) ;
- DisposeRoutineDescriptor( procs.rectProc ) ;
- DisposeRoutineDescriptor( procs.rRectProc ) ;
- DisposeRoutineDescriptor( procs.ovalProc ) ;
- DisposeRoutineDescriptor( procs.arcProc ) ;
- DisposeRoutineDescriptor( procs.polyProc ) ;
- DisposeRoutineDescriptor( procs.rgnProc ) ;
- DisposeRoutineDescriptor( procs.bitsProc ) ;
- DisposeRoutineDescriptor( procs.commentProc ) ;
-
- // Update the ticks parameter, if it was passed
- if (ticks)
- {
- if (err)
- *ticks = 0;
- else
- *ticks = gTicks;
- }
-
- // Update the pixel count parameter, if it was passed
- if (pixels)
- {
- if (err)
- *pixels = 0;
- else
- *pixels = gPixels;
- }
-
- return err;
- }
-
-
- /**\
- |**| ==============================================================================
- |**| PUBLIC FUNCTIONS
- |**| ==============================================================================
- \**/
-
-
- OSErr myDrawMatchedPicture ( PicHandle pict,
- CMProfileRef srceProf,
- CMProfileRef prevProf,
- Rect *rect,
- unsigned long *ticks,
- unsigned long *pixels )
- {
- gDrawMode = kMatch ;
- return myDrawPicture( pict, srceProf, prevProf, nil, rect, ticks, pixels ) ;
- }
-
-
- OSErr myDrawProofedPicture ( PicHandle pict,
- CMProfileRef srceProf,
- CMProfileRef destProf,
- CMProfileRef prevProf,
- Rect *rect,
- unsigned long *ticks,
- unsigned long *pixels )
- {
- gDrawMode = kProof ;
- return myDrawPicture( pict, srceProf, destProf, prevProf, rect, ticks, pixels ) ;
- }
-
-
- OSErr myDrawCheckedPicture ( PicHandle pict,
- CMProfileRef srceProf,
- CMProfileRef destProf,
- Rect *rect,
- unsigned long *ticks,
- unsigned long *pixels )
- {
- gDrawMode = kCheck ;
- return myDrawPicture( pict, srceProf, destProf, nil, rect, ticks, pixels ) ;
- }
-